/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../impl/head.h"
#include "big_buf_impl.h"

namespace xos_box
{
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static big_buf_impl::ITEM_DATA xos_item_data;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    big_buf_impl::big_buf_impl()
    {
        init_data();
    }

    big_buf_impl::~big_buf_impl()
    {
        term();
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int big_buf_impl::get_xos_item_data( ITEM_DATA*& item_ptr )
    {
        int ret = 0;
        xos_item_data.set_container( mgr::container() );
        item_ptr = &xos_item_data;
        return ret;
    }

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int big_buf_impl::init_data()
    {
        int ret = 0;
        m_szBuf[0] = 0;
        m_nLen = 0;
        m_nPos = 0;
        return ret;
    }

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int big_buf_impl::init()
    {
        int nRet = 0;
        return nRet;
    }

    int big_buf_impl::term()
    {
        int nRet = 0;
        init_data();
        return nRet;
    }

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // char * : char * data before get.
    //    int : get data len
    // 
	char * big_buf_impl::get_data( char * lpszData, int nWant, int * lpnGetLen, int * lpnLenNeeded )
	{
        int nPos = m_nPos;
        int nLen = m_nLen;
        int nGetLen = 0;
        if( lpszData )
        {
            nGetLen = nWant > m_nLen ? m_nLen : nWant;
            memcpy( lpszData, m_szBuf + m_nPos, nGetLen );
            m_nLen -= nGetLen;
            m_nPos += nGetLen;
        }
		if( lpnLenNeeded )
		{
			*lpnLenNeeded = nLen;
		}
        if( lpnGetLen )
        {
            *lpnGetLen = nGetLen;
        }
		return m_szBuf + nPos;
	}

	int big_buf_impl::get_data( xos_box::i_big_buf * pBuf, int nWant, int * lpnGetLen )
	{
        int ret = 0;
        int nLen = pBuf->get_len( 0 );
        int nSize = pBuf->get_buf_size( 0 ) - nLen;
        int nGetLen = nSize > nWant ? nWant : nSize;
        nGetLen = nGetLen > m_nLen ? m_nLen : nGetLen;
        if( nGetLen > 0 )
        {
            pBuf->move_data_to_begin();
            pBuf->add_data( m_szBuf + m_nPos, nGetLen, true );
            m_nLen -= nGetLen;
            m_nPos += nGetLen;
        }
        if( lpnGetLen )
        {
            *lpnGetLen = nGetLen;
        }
        ret = nGetLen;
        return ret;
	}

	int big_buf_impl::get_data( xos_box::i_buf * pBuf, int nWant, int * lpnGetLen )
	{
        int ret = 0;
        int nLen = pBuf->get_len( 0 );
        int nSize = pBuf->get_buf_size( 0 ) - nLen;
        int nGetLen = nSize > nWant ? nWant : nSize;
        nGetLen = nGetLen > m_nLen ? m_nLen : nGetLen;
        if( nGetLen > 0 )
        {
            pBuf->move_data_to_begin();
            pBuf->add_data( m_szBuf + m_nPos, nGetLen, true );
            m_nLen -= nGetLen;
            m_nPos += nGetLen;
        }
        if( lpnGetLen )
        {
            *lpnGetLen = nGetLen;
        }
        ret = nGetLen;
        return ret;
	}

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int big_buf_impl::set_end_zero()
    {
        int ret = 0;
        int pos = m_nLen + m_nPos;
        int nSize = get_buf_size( 0 );
        if( pos < nSize - 1 )
        {
            m_szBuf[pos] = 0;
        }
        return ret;
    }

    int big_buf_impl::reset()
    {
        int ret = 0;
        m_nLen = 0;
        m_nPos = 0;
        return ret;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 
    
    // 
    // ret : add data len
    // 
	int big_buf_impl::add_data( const char * lpszData, int nWant, bool bTail )
	{
        int ret = 0;
        int nSize = get_buf_size( 0 ) - m_nLen;
        int nAddLen = nSize > nWant ? nWant : nSize;
        int pos = 0;
        if( bTail )
        {
            move_data_to_begin();
            pos = m_nLen;
        }
        else
        {
            move_data_to_end();
            pos = nSize - nAddLen;
            m_nPos = pos;
        }
        if( nAddLen > 0 )
        {
            memcpy( m_szBuf + pos, lpszData, nAddLen );
            m_nLen += nAddLen;
        }
        ret = nAddLen;
        return ret;
	}

	int big_buf_impl::add_str( const char * lpszData, bool bTail )
	{
        int ret = 0;
        xos::i_crt * pCrt = mgr::container()->crt();
        int nLen = pCrt->strlen( lpszData );
        ret = add_data( lpszData, nLen, bTail );
        return ret;
	}

	int big_buf_impl::add_data( xos_box::i_big_buf * pBuf, bool bTail )
	{
        int ret = 0;
        int nLen = 0;
        char * lpszData = pBuf->get_data( 0, 0, 0, &nLen );
        ret = add_data( lpszData, nLen, bTail );
        return ret;
	}

	int big_buf_impl::add_data( xos_box::i_buf * pBuf, bool bTail )
	{
        int ret = 0;
        int nLen = 0;
        char * lpszData = pBuf->get_data( 0, 0, 0, &nLen );
        ret = add_data( lpszData, nLen, bTail );
        return ret;
	}

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

	int big_buf_impl::move_data_to_begin()
	{
		int ret = 0;
        xos::i_crt * pCrt = mgr::container()->crt();
		if( ( m_nPos != 0 ) && ( m_nLen > 0 ) )
		{
            pCrt->memmove( m_szBuf, m_szBuf + m_nPos, m_nLen );
		    m_nPos = 0;
		}
		return ret;
	}

    int big_buf_impl::move_data_to_end()
    {
        int ret = 0;
        xos::i_crt * pCrt = mgr::container()->crt();
        int nSize = get_buf_size( 0 );
        int pos = nSize - m_nLen;
        if( ( nSize > m_nLen ) && ( m_nPos != pos ) )
        {
            pCrt->memmove( m_szBuf + pos, m_szBuf + m_nPos, m_nLen );
            m_nPos = pos;
        }
        return ret;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // get data len
    // 
    int big_buf_impl::get_len( int * lpnDataLen )
    {
        if( lpnDataLen )
        {
            *lpnDataLen = m_nLen;
        }
        return m_nLen;
    }

    // 
    // set data len
    // 
    int big_buf_impl::set_len( int nLen )
    {
        int nRet = 0;
        m_nLen = nLen;
        return nRet;
    }

    // 
    // get data pos
    // 
    int big_buf_impl::get_pos( int * lpnPos )
    {
        if( lpnPos )
        {
            *lpnPos = m_nPos;
        }
        return m_nPos;
    }

    // 
    // set data pos
    // 
    int big_buf_impl::set_pos( int nPos )
    {
        int nRet = 0;
        m_nPos = nPos;
        return nRet;
    }

    // 
    // get buf size. total buf size
    // 
    int big_buf_impl::get_buf_size( int * lpnBufLen )
    {
        if( lpnBufLen )
        {
            *lpnBufLen = sizeof( m_szBuf );
        }
        return sizeof( m_szBuf );
    }
} // xos
